/*
* s-utils v4.0.0
* author 无痕
* (c) Mon Mar 21 2022 11:29:13 GMT+0800 (中国标准时间)
* @license MIT
*/
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = global || self, factory(global.S = {}));
}(this, (function (exports) { 'use strict';

  /**
   * @description: 判断是不是一个有效值
   * @param {*} val
   * @return {Boolean}
   * @example: isDef(1) // true
   */
  function isDef(val) {
    return val !== undefined && val !== null && val !== '';
  }

  /**
   * @description: 去掉字符串空格
   * @param {String} str
   * @param {String} pos both：左右2边空格， left：左边空格，right：右边空格，all：全部空格
   * @return {String}
   */

  function trim(str) {
    var pos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'both';
    str = String(isDef(str) ? str : '');

    if (pos == 'both') {
      return str.replace(/^\s+|\s+$/g, '');
    } else if (pos == 'left') {
      return str.replace(/^\s*/, '');
    } else if (pos == 'right') {
      return str.replace(/(\s*$)/g, '');
    } else if (pos == 'all') {
      return str.replace(/\s+/g, '');
    } else {
      return str;
    }
  }

  function _typeof(obj) {
    "@babel/helpers - typeof";

    return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
      return typeof obj;
    } : function (obj) {
      return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
    }, _typeof(obj);
  }

  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }

  function _defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }

  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    Object.defineProperty(Constructor, "prototype", {
      writable: false
    });
    return Constructor;
  }

  function _slicedToArray(arr, i) {
    return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
  }

  function _toConsumableArray(arr) {
    return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
  }

  function _arrayWithoutHoles(arr) {
    if (Array.isArray(arr)) return _arrayLikeToArray(arr);
  }

  function _arrayWithHoles(arr) {
    if (Array.isArray(arr)) return arr;
  }

  function _iterableToArray(iter) {
    if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
  }

  function _iterableToArrayLimit(arr, i) {
    var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];

    if (_i == null) return;
    var _arr = [];
    var _n = true;
    var _d = false;

    var _s, _e;

    try {
      for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
        _arr.push(_s.value);

        if (i && _arr.length === i) break;
      }
    } catch (err) {
      _d = true;
      _e = err;
    } finally {
      try {
        if (!_n && _i["return"] != null) _i["return"]();
      } finally {
        if (_d) throw _e;
      }
    }

    return _arr;
  }

  function _unsupportedIterableToArray(o, minLen) {
    if (!o) return;
    if (typeof o === "string") return _arrayLikeToArray(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === "Object" && o.constructor) n = o.constructor.name;
    if (n === "Map" || n === "Set") return Array.from(o);
    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
  }

  function _arrayLikeToArray(arr, len) {
    if (len == null || len > arr.length) len = arr.length;

    for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];

    return arr2;
  }

  function _nonIterableSpread() {
    throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  }

  function _nonIterableRest() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  }

  /**
   * @description: 判断是否为类数组
   * @param {*} o
   * @return {boolean}
   * @example isArrayLike({0:1,1:2,length:2}) // true
   */
  function isArrayLike(o) {
    return o && _typeof(o) === 'object' && isFinite(o.length) && o.length >= 0 && o.length === Math.floor(o.length) && o.length < 4294967296;
  }

  /**
   * @description: 转数组
   * @param {*} list
   * @return {array}
   */

  function toArray(list) {
    return isArrayLike(list) ? Array.prototype.slice.call(list) : [];
  }

  /**
   * @description: 获取或生成dom节点
   * @param {string|Element|Element[]} selector
   * @param {Element} context
   * @return {Element[]}
   * @example getElem('div')
   */

  function getElem(selector, context) {
    var arr = [];

    if (selector) {
      if (typeof selector === 'string') {
        selector = selector.trim();

        if (selector.indexOf('<') >= 0 && selector.indexOf('>') >= 0) {
          var tag = 'div';
          if (selector.indexOf('<li') === 0) { tag = 'ul'; }
          if (selector.indexOf('<tr') === 0) { tag = 'tbody'; }
          if (selector.indexOf('<td') === 0 || selector.indexOf('<th') === 0) { tag = 'tr'; }
          if (selector.indexOf('<tbody') === 0) { tag = 'table'; }
          if (selector.indexOf('<option') === 0) { tag = 'select'; }
          var el = document.createElement(tag);
          el.innerHTML = selector;
          arr = toArray(el.children);
        } else {
          arr = toArray((context || document).querySelectorAll(selector));
        }
      } else if (selector.nodeType) {
        arr = [selector];
      } else {
        arr = toArray(selector).filter(function (el) {
          return el.nodeType;
        });
      }
    }

    return arr;
  }

  /**
   * @description: 添加class
   * @param {string|Element|Element[]} selector
   * @param {string} value
   * @return {void}
   * @example addClass('body','class1')
   */

  function addClass(selector, value) {
    value = trim(value);

    if (value) {
      var classes = value.split(/\s+/g);
      getElem(selector).forEach(function (el) {
        var cur = ' ' + (el.getAttribute('class') || '').trim() + ' ';
        classes.forEach(function (cls) {
          if (cur.indexOf(' ' + cls + ' ') < 0) {
            cur += cls + ' ';
          }
        });
        el.setAttribute('class', cur.trim());
      });
    }
  }

  /**
   * @description: 判断是否可以转number
   * @param {String|Number} value
   * @return {boolean}
   * @example isNumber('5') // true
   */

  function isNumber(value) {
    if (typeof value === 'number') { return true; }
    if (typeof value === 'string' && trim(value)) { return !isNaN(value); }
    return false;
  }

  /**
   * @description: 添加单位
   * @param {String|Number} value ''
   * @param {String} unit px
   * @return {String} ''
   * @example addUnit(30) // 30px
   */

  function addUnit() {
    var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
    var unit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'px';
    return isNumber(value) ? Number(value) + unit : value;
  }

  /**
   * @description: 数组差集
   * @param {Array} arr1
   * @param {Array} arr2
   * @return {Array}
   * @example: arrayDifference([1,2,3],[2,3]) //[1]
   */
  function arrayDifference() {
    var arr1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
    var arr2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
    var set1 = new Set(arr1);
    var set2 = new Set(arr2);
    return _toConsumableArray(new Set(_toConsumableArray(set1).filter(function (x) {
      return !set2.has(x);
    })));
  }

  /**
   * @description: 数组item查询
   * @param {Array} list
   * @param {String} key
   * @param {*} value
   */
  function arrayFind() {
    var list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
    var key = arguments.length > 1 ? arguments[1] : undefined;
    var value = arguments.length > 2 ? arguments[2] : undefined;
    var attr = arguments.length > 3 ? arguments[3] : undefined;
    var item = list.find(function (item) {
      return item[key] == value;
    });
    if (typeof attr !== 'undefined') { return item === null || item === void 0 ? void 0 : item[attr]; }
    return item;
  }

  /**
   * @description: 数组交集
   * @param {Array} arr1
   * @param {Array} arr2
   * @return {Array}
   * @example: arrayIntersect([1,2,3],[2,3,4]) //[2, 3]
   */
  function arrayIntersect() {
    var arr1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
    var arr2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
    var set1 = new Set(arr1);
    var set2 = new Set(arr2);
    return _toConsumableArray(new Set(_toConsumableArray(set1).filter(function (x) {
      return set2.has(x);
    })));
  }

  /**
   * @description: 数组并集
   * @param {Array} arr1
   * @param {Array} arr2
   * @return {Array}
   * @example: arrayUnion([1,2,3],[2,3,4]) //[1, 2, 3, 4]
   */
  function arrayUnion() {
    var arr1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
    var arr2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
    var set1 = new Set(arr1);
    var set2 = new Set(arr2);
    return _toConsumableArray(new Set([].concat(_toConsumableArray(set1), _toConsumableArray(set2))));
  }

  // 下面是64个基本的编码
  var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  var base64DecodeChars = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1];
  /**
   * @description: base64加密
   * @param {string} str
   * @return {string}
   * @example encode(123) // MTIz
   */

  function encode() {
    var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
    str = String(str);
    var out, i, len;
    var c1, c2, c3;
    len = str.length;
    i = 0;
    out = '';

    while (i < len) {
      c1 = str.charCodeAt(i++) & 0xff;

      if (i === len) {
        out += base64EncodeChars.charAt(c1 >> 2);
        out += base64EncodeChars.charAt((c1 & 0x3) << 4);
        out += '==';
        break;
      }

      c2 = str.charCodeAt(i++);

      if (i === len) {
        out += base64EncodeChars.charAt(c1 >> 2);
        out += base64EncodeChars.charAt((c1 & 0x3) << 4 | (c2 & 0xf0) >> 4);
        out += base64EncodeChars.charAt((c2 & 0xf) << 2);
        out += '=';
        break;
      }

      c3 = str.charCodeAt(i++);
      out += base64EncodeChars.charAt(c1 >> 2);
      out += base64EncodeChars.charAt((c1 & 0x3) << 4 | (c2 & 0xf0) >> 4);
      out += base64EncodeChars.charAt((c2 & 0xf) << 2 | (c3 & 0xc0) >> 6);
      out += base64EncodeChars.charAt(c3 & 0x3f);
    }

    return out;
  }
  /**
   * @description: base64解密
   * @param {string} str
   * @return {string}
   * @example decode('MTIz') // 123
   */


  function decode() {
    var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
    var c1, c2, c3, c4;
    var i, len, out;
    len = str.length;
    i = 0;
    out = '';

    while (i < len) {
      do {
        c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
      } while (i < len && c1 === -1);

      if (c1 === -1) {
        break;
      }

      do {
        c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
      } while (i < len && c2 === -1);

      if (c2 === -1) {
        break;
      }

      out += String.fromCharCode(c1 << 2 | (c2 & 0x30) >> 4);

      do {
        c3 = str.charCodeAt(i++) & 0xff;

        if (c3 === 61) {
          return out;
        }

        c3 = base64DecodeChars[c3];
      } while (i < len && c3 === -1);

      if (c3 === -1) {
        break;
      }

      out += String.fromCharCode((c2 & 0xf) << 4 | (c3 & 0x3c) >> 2);

      do {
        c4 = str.charCodeAt(i++) & 0xff;

        if (c4 === 61) {
          return out;
        }

        c4 = base64DecodeChars[c4];
      } while (i < len && c4 === -1);

      if (c4 === -1) {
        break;
      }

      out += String.fromCharCode((c3 & 0x03) << 6 | c4);
    }

    return out;
  }

  var base64 = {
    encode: encode,
    decode: decode
  };

  /**
   * @description: 用于默认Function赋值
   */
  function noop() {}

  /**
   * @description: 与app通信
   * @param {Function} callback
   * @return {void}
   */

  function setupWebViewJavascriptBridge(callback) {
    if (window.WebViewJavascriptBridge) {
      return callback(window.WebViewJavascriptBridge);
    }

    if (window.WVJBCallbacks) {
      return window.WVJBCallbacks.push(callback);
    }

    window.WVJBCallbacks = [callback];
    var WVJBIframe = document.createElement('iframe');
    WVJBIframe.style.display = 'none';
    WVJBIframe.src = 'https://__bridge_loaded__';
    document.documentElement.appendChild(WVJBIframe);
    setTimeout(function () {
      document.documentElement.removeChild(WVJBIframe);
    }, 0);
  }
  /**
   * @description: 在需要调用客户端方法的组件中（事先需要与客户端同事约定好方法名）
   * @param {string} event
   * @param {any} data
   * @param {function(*) void} callback
   * @return {void}
   */


  function callHandler(event, data) {
    var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : noop;
    setupWebViewJavascriptBridge(function (bridge) {
      bridge.callHandler(event, data, callback);
    });
  }
  /**
   * @description: 当客户端需要调用 js 函数时,事先注册约定好的函数即可
   * @param {string} event
   * @param {function(*,function?):void} callback
   * @return {void}
   */


  function registerHandler(event, callback) {
    setupWebViewJavascriptBridge(function (bridge) {
      bridge.registerHandler(event, function (data, responseCallback) {
        callback(data, responseCallback);
      });
    });
  }

  var bridge = {
    callHandler: callHandler,
    registerHandler: registerHandler
  };

  /**
   * @description: 拨打电话
   * @param {String} phoneNumber
   * @return {void}
   * @example callPhone('15234855555')
   */
  function callPhone(phoneNumber) {
    window.location.href = "tel:".concat(phoneNumber);
  }

  var CookieStorage = /*#__PURE__*/function () {
    function CookieStorage() {
      _classCallCheck(this, CookieStorage);
    }

    _createClass(CookieStorage, [{
      key: "setItem",
      value:
      /**
       * @description: 设置cookie
       * @param {string} key
       * @param {string} value
       * @param {number} days
       * @param {object} options
       * @return {void}
       */
      function setItem(key, value, days) {
        var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};

        if (value !== undefined) {
          var expires;

          if (typeof days === 'number') {
            expires = new Date();
            expires.setTime(+expires + days * 864e+5);
          }

          return document.cookie = [encodeURIComponent(key), '=', encodeURIComponent(value), expires ? '; expires=' + expires.toUTCString() : '', options.path ? '; path=' + options.path : '', options.domain ? '; domain=' + options.domain : '', options.secure ? '; secure' : ''].join('');
        }
      }
      /**
       * @description: 获取cookie
       * @param {string} key
       * @return {string}
       */

    }, {
      key: "getItem",
      value: function getItem(key) {
        var result = null;

        if (document.cookie) {
          document.cookie.split('; ').some(function (item) {
            var parts = item.split('=');
            var keyStr = parts.shift();

            if (keyStr && keyStr === encodeURIComponent(key)) {
              result = decodeURIComponent(parts.join('='));
              return true;
            }
          });
        }

        return result;
      }
      /**
       * @description: 删除cookie
       * @param {string} key
       * @param {object} options
       * @return {void}
       */

    }, {
      key: "removeItem",
      value: function removeItem(key) {
        var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
        this.setItem(key, '', -1, options);
      }
      /**
       * @description: 计算属性，获取cookie长度
       * @return {Number}
       */

    }, {
      key: "length",
      get: function get() {
        return (document.cookie.match(/[^ =;]+(?==)/g) || []).length;
      }
      /**
       * @description: 清空所有cookie
       * @param {object} options
       * @return {void}
       */

    }, {
      key: "clear",
      value: function clear() {
        var _this = this;

        var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
        (document.cookie.match(/[^ =;]+(?==)/g) || []).forEach(function (key) {
          _this.removeItem(decodeURIComponent(key), options);
        });
      }
    }]);

    return CookieStorage;
  }();

  var cookieStorage = new CookieStorage();

  /**
   * @description: 复制文本
   * @param {string} value
   * @return {void}
   */

  function copyText(value) {
    var input = getElem("<input value=\"".concat(value, "\" style=\"position: absolute;left:0;top:0;opacity:0;z-index:-1\"/>"))[0];
    document.body.appendChild(input);
    input.select();
    document.execCommand('copy');
    document.body.removeChild(input);
  }

  /**
   * @description: 创建一个定时控制器
   * @param {function} fn 每次执行回调
   * @param {number} wait 间隔时间 5000
   * @param {boolean} immediate 初始化是否启动，false
   * @return {object} {start:Function,stop:Function}返回一个对象，可暂停和启动
   * @example createTimer(()=>console.log('执行'))
   */
  function createTimer(fn) {
    var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5000;
    var immediate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
    var timerId = null;
    var isStop = true;

    var start = function start() {
      if (isStop) {
        isStop = false;
        fn(next, stop);
      }

      return this;
    };

    var next = function next() {
      if (!isStop) {
        stop();
        timerId = setTimeout(start, wait);
      }
    };

    var stop = function stop() {
      isStop = true;

      if (timerId) {
        clearTimeout(timerId);
        timerId = null;
      }

      return this;
    };

    if (immediate) { start(); }
    return {
      start: start,
      stop: stop
    };
  }

  function isSameSecond(time1, time2) {
    return Math.floor(time1 / 1000) === Math.floor(time2 / 1000);
  }
  /**
   * @description: 倒计时控制器
   * @param {{ time: Number, millisecond?: Boolean, onChange?: Function, onFinish?: Function }} options
   * @return {{ start: Function, stop: Function, reset: Function, finish: Function }}
   */


  function countDown(options) {
    var _Object$assign = Object.assign({
      time: 0,
      millisecond: false,
      onChange: null,
      onFinish: null
    }, options),
        time = _Object$assign.time,
        millisecond = _Object$assign.millisecond,
        onChange = _Object$assign.onChange,
        onFinish = _Object$assign.onFinish;

    var remain = time;
    var endTime = 0;

    var getCurrentRemain = function getCurrentRemain() {
      return Math.max(endTime - Date.now(), 0);
    };

    var setRemain = function setRemain(value) {
      remain = value;
      onChange && onChange(remain);

      if (remain === 0) {
        stop();
        onFinish && onFinish();
      }
    };

    var timer = createTimer(function (next) {
      var currentRemain = getCurrentRemain();

      if (millisecond) {
        setRemain(currentRemain);
      } else {
        if (!isSameSecond(currentRemain, remain) || currentRemain === 0) {
          setRemain(currentRemain);
        }
      }

      if (remain > 0) {
        next();
      }
    }, 30, false);

    var start = function start() {
      endTime = Date.now() + remain;
      timer.start();
      return this;
    };

    var stop = function stop() {
      timer.stop();
      return this;
    };

    var reset = function reset(newTime) {
      timer.stop();
      setRemain(typeof newTime === 'number' ? newTime : time);
      return this;
    };

    var finish = function finish() {
      timer.stop();
      setRemain(0);
      return this;
    };

    return {
      start: start,
      stop: stop,
      reset: reset,
      finish: finish
    };
  }

  /**
   * @description: 有些函数采用可变数量的参数，或采用一些预期参数
  参数，然后是要操作的可变数量的值
  在…上此帮助程序将所有剩余参数累加到函数的
  参数长度（或显式的“startIndex”）转换为
  最后一个论点。类似于ES6的“rest参数”。
   * @param {Function} func
   * @param {Number} startIndex
   * @return {Function}
   */
  function restArguments(func, startIndex) {
    startIndex = startIndex == null ? func.length - 1 : +startIndex;
    return function () {
      var arguments$1 = arguments;

      var length = Math.max(arguments.length - startIndex, 0);
      var rest = Array(length);
      var index = 0;

      for (; index < length; index++) {
        rest[index] = arguments$1[index + startIndex];
      }

      switch (startIndex) {
        case 0:
          return func.call(this, rest);

        case 1:
          return func.call(this, arguments[0], rest);

        case 2:
          return func.call(this, arguments[0], arguments[1], rest);
      }

      var args = Array(startIndex + 1);

      for (index = 0; index < startIndex; index++) {
        args[index] = arguments$1[index];
      }

      args[startIndex] = rest;
      return func.apply(this, args);
    };
  }

  /**
   * @description: 函数防抖
   * @param {Function} func 回调函数
   * @param {Number} wait 等待时间
   * @param {Boolean} immediate 首次触发是否立即执行，true
   * @return {Function}
   * @example const func = debounce(()=>console.log(1),100);
   */

  function debounce(func) {
    var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
    var immediate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
    var timeout, previous, args, result, context;

    var later = function later() {
      var passed = Date.now() - previous;

      if (wait > passed) {
        timeout = setTimeout(later, wait - passed);
      } else {
        timeout = null;
        if (!immediate) { result = func.apply(context, args); }
        if (!timeout) { args = context = null; }
      }
    };

    var debounced = restArguments(function (_args) {
      context = this;
      args = _args;
      previous = Date.now();

      if (!timeout) {
        timeout = setTimeout(later, wait);
        if (immediate) { result = func.apply(context, args); }
      }

      return result;
    });

    debounced.cancel = function () {
      clearTimeout(timeout);
      timeout = args = context = null;
    };

    return debounced;
  }

  /**
   * @description: 浏览器下载blob文件流
   * @param {Blob} blob
   * @param {String} filename
   * @return {void}
   * @example downloadBlob(blob, 'test.xlsx')
   */
  function downloadBlob(blob, filename) {
    var a = document.createElement('a');
    var href = window.URL.createObjectURL(blob);
    a.href = href; // 创建下载的链接

    a.download = filename; // 下载后文件名

    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    window.URL.revokeObjectURL(href); // 释放掉blob对象
  }

  /**
   * @description: 数组和对象循环
   * @param {object|array} obj
   * @param {function(item,key,obj):boolean?} callback(item,key,obj)
   * @return {void}
   * @example each([1,2,3], (item,index,list)=>{})
   */

  function each(obj, callback) {
    if (!obj) { return; }

    if (isArrayLike(obj)) {
      for (var i = 0, len = obj.length; i < len; i++) {
        if (callback(obj[i], i, obj) === false) {
          break;
        }
      }
    } else {
      for (var _i = 0, _Object$keys = Object.keys(obj); _i < _Object$keys.length; _i++) {
        var key = _Object$keys[_i];

        if (callback(obj[key], key, obj) === false) {
          break;
        }
      }
    }
  }

  /**
   * @description: 获取数据类型
   * @param {*} value
   * @return {string}
   * @example getType({}) // object
   */
  function getType(value) {
    return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
  }

  /**
   * @description: 判断是否为function
   * @param {*} value
   * @return {boolean}
   * @example isFunction(()=>{}) // true
   */

  function isFunction(value) {
    return getType(value) === 'function';
  }

  /**
   * @description: 判断是否为object
   * @param {*} value
   * @return {boolean}
   * @example isObject({}) // true
   */

  function isObject(value) {
    return getType(value) === 'object';
  }

  /**
   * @description: 判断是否是此对象上的实例属性
   * @param {object} obj
   * @param {string} prop
   * @return {boolean}
   * @example hasOwnProp({a:1},'a') // true
   */
  function hasOwnProp(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }

  var isOnce = '[S_EVENT_EMIT_IS_ONCE]';
  var events = '[S_EVENT_EMIT_EVENTS]';
  /**
   * @description: 
   * @param {string} name
   * @param {Function} fn
   * @return {void}
   */

  function addEvent(name, _fn) {
    var _this = this;

    if (isFunction(_fn)) {
      name = trim(name);

      if (this[isOnce]) {
        _fn = function fn() {
          _this.off(name, _fn);

          _fn.apply(void 0, arguments);
        };
      }

      if (!hasOwnProp(this[events], name)) {
        this[events][name] = [_fn];
      } else {
        this[events][name].push(_fn);
      }
    }
  }

  var EventEmit = /*#__PURE__*/function () {
    function EventEmit() {
      _classCallCheck(this, EventEmit);

      this[isOnce] = false; // 执行一次的绑定判断

      this[events] = {}; // 存储函数对象
    } // 订阅消息


    _createClass(EventEmit, [{
      key: "on",
      value: function on() {
        var arguments$1 = arguments;

        var _this2 = this;

        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments$1[_key];
        }

        if (isObject(args[0])) {
          each(args[0], function (fn, name) {
            addEvent.call(_this2, name, fn);
          });
        } else {
          addEvent.call.apply(addEvent, [this].concat(args));
        }

        return this;
      } // 订阅一次消息

    }, {
      key: "once",
      value: function once() {
        this[isOnce] = true;
        this.on.apply(this, arguments);
        this[isOnce] = false;
        return this;
      } // 发布消息

    }, {
      key: "emit",
      value: function emit(name) {
        var arguments$1 = arguments;

        var _this3 = this;

        for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
          args[_key2 - 1] = arguments$1[_key2];
        }

        name = trim(name);

        if (this[events] && hasOwnProp(this[events], name)) {
          each(this[events][name], function (fn) {
            fn.call.apply(fn, [_this3].concat(args));
          });
        }

        return this;
      } // 取消订阅

    }, {
      key: "off",
      value: function off(name, fn) {
        if (arguments.length) {
          name = trim(name);

          if (this[events] && hasOwnProp(this[events], name)) {
            if (fn !== undefined) {
              var index = this[events][name].indexOf(fn);
              index > -1 && this[events][name].splice(index, 1);
            } else {
              this[events][name] = [];
            }

            if (!this[events][name].length) {
              delete this[events][name];
            }
          }
        } else {
          this[events] = {};
        }

        return this;
      }
    }]);

    return EventEmit;
  }();

  /**
   * @description: 判断指定参数是否是一个纯粹的对象
   * @param {object} obj
   * @return {boolean}
   */

  function isPlainObject(obj) {
    if (!obj || getType(obj) !== 'object') {
      return false;
    }

    var proto = Object.getPrototypeOf(obj);

    if (!proto) {
      return true;
    }

    var ctor = hasOwnProp(proto, 'constructor') && proto.constructor;
    var fnToString = Object.hasOwnProperty.toString;
    return typeof ctor === 'function' && fnToString.call(ctor) === fnToString.call(Object);
  }

  /**
   * @description: 判断是否为数组
   * @param {*} value
   * @return {boolean}
   * @example isArray([]) // true
   */

  function isArray(value) {
    return getType(value) === 'array';
  }

  /**
   * @description: 对象合并，对象拷贝
   * @param {object} args
   * @return {object}
   * @example extend(obj,obj1,obj2...)//浅合并  
   * @example extend(true,obj,obj1,obj2...)//深度合并 
   */

  function extend() {
    var arguments$1 = arguments;

    var options;
    var name;
    var src;
    var copy;
    var copyIsArray;
    var clone;

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments$1[_key];
    }

    var target = args[0] || {};
    var i = 1;
    var length = args.length;
    var deep = false; // Handle a deep copy situation

    if (typeof target === 'boolean') {
      deep = target; // Skip the boolean and the target

      target = args[i] || {};
      i++;
    } // Handle case when target is a string or something (possible in deep copy)


    if (_typeof(target) !== 'object' && !isFunction(target)) {
      target = {};
    }

    for (; i < length; i++) {
      // Only deal with non-null/undefined values
      if ((options = args[i]) != null) {
        // Extend the base object
        for (name in options) {
          copy = options[name]; // Prevent Object.prototype pollution
          // Prevent never-ending loop

          if (name === '__proto__' || target === copy) {
            continue;
          } // Recurse if we're merging plain objects or arrays


          if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
            src = target[name]; // Ensure proper type for the source value

            if (copyIsArray && !isArray(src)) {
              clone = [];
            } else if (!copyIsArray && !isPlainObject(src)) {
              clone = {};
            } else {
              clone = src;
            }

            copyIsArray = false; // Never move original objects, clone them

            target[name] = extend(deep, clone, copy); // Don't bring in undefined values
          } else if (copy !== undefined) {
            target[name] = copy;
          }
        }
      }
    } // Return the modified object


    return target;
  }

  /**
   * @description: 判断是否可以转为一个合法的时间对象
   * @param {*} date
   * @return {boolean}
   */
  function isValidDate(date) {
    return !/Invalid|NaN/.test(new Date(date).toString());
  }

  /**
   * @description: 尝试转一个合法Date对象,兼容ios
   * @param {string|Date|number} date
   * @return {Date}
   * @example parseDate('2021-05-17') // Mon May 17 2021 08:00:00 GMT+0800 (中国标准时间)
   */

  function parseDate(date) {
    if (!date) { return; }

    if (typeof date === 'string') {
      if (/^\d*$/.test(date)) {
        date = Number(date);
      } else if (!isValidDate(date)) {
        date = date.replace(/-/g, '/').replace(/(\.0)$/, '');
      }
    }

    return new Date(date);
  }

  /**
   * @description: 格式化时间
   * @param {Date|Number|String} date
   * @param {String} fmt = 'YYYY-MM-DD HH:mm'
   * @return {String}
   * @example formatDate(new Date(), fmt = 'YYYY-MM-DD HH:mm')
   */

  function formatDate(date) {
    var fmt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'YYYY-MM-DD HH:mm';
    if (!isValidDate(date = parseDate(date))) { return ''; }
    var o = {
      'M+': date.getMonth() + 1,
      // 月份
      '(D|d)+': date.getDate(),
      // 日
      'h+': date.getHours() % 12 == 0 ? 12 : date.getHours() % 12,
      // 小时
      'H+': date.getHours(),
      // 小时
      'm+': date.getMinutes(),
      // 分
      's+': date.getSeconds(),
      // 秒
      'q+': Math.floor((date.getMonth() + 3) / 3),
      // 季度
      'S+': date.getMilliseconds() // 毫秒

    };

    if (/(Y+)/i.test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
    }

    if (/(E+)/.test(fmt)) {
      fmt = fmt.replace(RegExp.$1, ['日', '一', '二', '三', '四', '五', '六'][date.getDay()]);
    }

    Object.keys(o).forEach(function (k) {
      if (new RegExp('(' + k + ')').test(fmt)) {
        fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : ('0'.repeat(RegExp.$1.length) + o[k]).substr(('' + o[k]).length));
      }
    });
    return fmt;
  }

  /**
   * @description: 格式化时间段
   * @param {Date|Number|String} startDateTime
   * @param {Date|Number|String} endDateTime
   * @param {String} separator ~
   * @param {String} startformat
   * @param {String} endformat
   * @return {String}
   * @example formatDateRange(new Date(),new Date())
   */

  function formatDateRange(startDateTime, endDateTime) {
    var separator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ' ~ ';
    var startformat = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'YYYY-MM-DD HH:mm';
    var endformat = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'YYYY-MM-DD HH:mm';
    return startDateTime && endDateTime ? formatDate(startDateTime, startformat) + separator + formatDate(endDateTime, endformat) : '';
  }

  /**
   * @description: 格式化日期为今天，明天，后天，周几
   * @param {Date | String | Number} date
   * @param {Number} num 0,1,2,3
   * @return {String}
   * @example formatDay(new Date())
   */

  function formatDay(date, num) {
    if (!isValidDate(date = parseDate(date))) { return ''; }
    num = parseInt(num) || 1;
    var nowTime = new Date(formatDate(new Date(), 'YYYY/MM/DD')).getTime();
    var dayTime = 24 * 60 * 60 * 1000;
    var dateTime = new Date(formatDate(date, 'YYYY/MM/DD')).getTime();
    var dayName = ([{
      label: '今天',
      value: nowTime
    }, {
      label: '明天',
      value: nowTime + dayTime
    }, {
      label: '后天',
      value: nowTime + dayTime * 2
    }].slice(0, num).find(function (item) {
      return item.value == dateTime;
    }) || {
      label: ''
    }).label;
    return formatDate(date, "".concat(dayName || '周E'));
  }

  var list = [{
    k: 'w',
    modulo: 60 * 60 * 24 * 7 * 1000
  }, {
    k: 'd',
    modulo: 60 * 60 * 24 * 1000
  }, {
    k: 'h',
    modulo: 60 * 60 * 1000
  }, {
    k: 'm',
    modulo: 60 * 1000
  }, {
    k: 's',
    modulo: 1000
  }, {
    k: 'S',
    modulo: 1
  }];
  /**
   * @description: 格式化毫秒为对象
   * @param {Number} time
   * @param {String|Array} fmt 默认 'd,h,m,s,S'
   * @return {object} {d,d2,h,h2,m,m2,s,s2,S,S1,S2,S3}
   * @example parseMilliseconds(5*1000) // {d:0,d2:'00',h:0,h2:'00',m:0,m2:'00',s:5,s2:'05',S:0,S1:'0',S2:'00',S3:'000'}
   */

  function parseMilliseconds(time) {
    var fmt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'd,h,m,s,S';
    var obj = {};
    list.forEach(function (_ref) {
      var k = _ref.k,
          modulo = _ref.modulo;

      if (fmt.indexOf(k) > -1) {
        var val = Math.floor(time / modulo);
        obj[k] = val;
        time -= val * modulo;

        if (k === 'S') {
          [1, 2, 3].forEach(function (len) {
            obj["S".concat(len)] = String(val).slice(0, len).padStart(len, '0');
          });
        } else {
          obj["".concat(k, "2")] = String(val).padStart(2, '0');
        }
      }
    });
    return obj;
  }

  /**
   * @description: 格式化秒为对象
   * @param {Number} time
   * @param {String|Array} fmt 默认 'd,h,m,s'
   * @return {object} {d,d2,h,h2,m,m2,s,s2}
   * @example parseSeconds(5*60) // {d: 0, d2: '00', h: 0, h2: '00', m: 5, m2: '05', s: 0, s2: '00'}
   */

  function parseSeconds() {
    var seconds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
    var fmt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'd,h,m,s';
    return parseMilliseconds(seconds * 1000, fmt);
  }

  /**
   * @description: 格式化时间差，
   * @param {Date|Number|String} date
   * @param {Date|Number|String} now 默认与当前时间相比
   * @param {Number} maxDays
   * @param {String} nowStr '刚刚'
   * @return {String}
   * @example formatDiffTime(date, now, maxDays = 7, nowStr = '刚刚')
   */

  function formatDiffTime(date, now) {
    var maxDays = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 7;
    var nowStr = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '刚刚';
    now = now || new Date();
    maxDays = maxDays || 7;
    if (!isValidDate(date = parseDate(date)) || !isValidDate(now = parseDate(now))) { return ''; }
    var diff = Math.floor((now.getTime() - date.getTime()) / 1000);
    if (diff === 0) { return nowStr; }
    var suffix = diff > 0 ? '前' : '后';

    var _parseSeconds = parseSeconds(Math.abs(diff)),
        d = _parseSeconds.d,
        h = _parseSeconds.h,
        m = _parseSeconds.m,
        s = _parseSeconds.s;

    if (d > maxDays) {
      return formatDate(date, 'YYYY-MM-DD');
    }

    if (d) {
      return d + "\u5929".concat(suffix);
    } else if (h) {
      return h + "\u5C0F\u65F6".concat(suffix);
    } else if (m) {
      return m + "\u5206\u949F".concat(suffix);
    } else if (s) {
      return s + "\u79D2".concat(suffix);
    }
  }

  /**
   * @description: 格式化数字
   * @param {Number} number 数字
   * @param {Number} places 在有小数时保留的小位数，默认0位
   * @param {String} thousand 用啥隔开：','
   * @param {String} decimal 表示小数点:'.'
   * @return {String}
   * @example formatNumber(12345) // 12,345
   */
  function formatNumber() {
    var number = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
    var places = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
    var thousand = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ',';
    var decimal = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '.';
    number = +number || 0;
    var negative = number < 0 ? '-' : '';
    var i = parseInt(Math.abs(number)) + '';
    var j = i.length > 3 ? i.length % 3 : 0;
    var decimalIndex = ('' + number).lastIndexOf('.');
    return negative + (j ? i.substr(0, j) + thousand : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand) + (places > 0 && decimalIndex > -1 ? decimal + ('' + number).substr(decimalIndex + 1, places).padEnd(places, '0') : '');
  }

  /**
   * @description: 格式化货币
   * @param {Number} number 货币数字
   * @param {Number} places 在有小数时保留的小位数，默认2位
   * @param {String} symbol 货币符号：'￥'
   * @param {String} thousand 用啥隔开：','
   * @param {String} decimal 表示小数点符合:'.'
   * @return {String}
   * @example formatMoney(12345) // ￥12,345
   */

  function formatMoney() {
    var number = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
    var places = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
    var symbol = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '￥';
    var thousand = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ',';
    var decimal = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '.';
    return symbol + formatNumber(number, places, thousand, decimal);
  }

  /**
   * @description: 根据生日获取星座
   * @param {Date|Number|String} date
   * @return {String}
   */

  function getAstro(date) {
    date = parseDate(date);
    var month = date.getMonth() + 1;
    var day = date.getDate();
    var s = '摩羯水瓶双鱼白羊金牛双子巨蟹狮子处女天秤天蝎射手摩羯';
    var arr = [20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22];
    return s.substr(month * 2 - (day < arr[month - 1] ? 2 : 0), 2);
  }

  /**
   * @description: 获取某年某月有多少天
   * @param {String|Number} year
   * @param {String|Number} month
   * @return {Number}
   * @example getDaysInMonth(2021,2) // 28
   */
  function getDaysInMonth() {
    var year = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
    var month = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
    var curDate = new Date("".concat(year, "/").concat(String(month).padStart(2, '0'), "/01"));
    /* 获取当前月份 */

    var curMonth = curDate.getMonth();
    /* 生成实际的月份: 由于curMonth会比实际月份小1, 故需加1 */

    curDate.setMonth(curMonth + 1);
    /* 将日期设置为0 */

    curDate.setDate(0);
    /* 返回当月的天数 */

    return curDate.getDate();
  }

  /**
   * @description: 获取根节点到匹配节点的链数组
   * @param {Array} list
   * @param {string} childrenKey
   * @param {Function} validator
   * @param {Array} matcheds
   * @return {Array}
   */
  function getMatcheds(list, childrenKey, validator) {
    var matcheds = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];

    for (var i = 0, l = list.length; i < l; i++) {
      var item = list[i];

      if (validator(item, matcheds)) {
        matcheds.push(item);
        return matcheds;
      } else if (item[childrenKey] && item[childrenKey].length) {
        var result = getMatcheds(item[childrenKey], childrenKey, validator, matcheds.concat(item));

        if (result) {
          return result;
        }
      }
    }
  }

  /**
   * @description: 获取浏览器中最大z-index值
   * @param {string|Element|Element[]} selector
   * @param {number} minZindex
   * @return {number}
   */

  function getMaxZindex() {
    var selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '*';
    var minZindex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
    return Math.max.apply(null, [Math.max(1, parseInt(minZindex) || 1)].concat(getElem(selector).map(function (el) {
      return parseInt(el.style.zIndex) || 1;
    })));
  }

  /**
   * @description: 获取指定位数的随机数
   * @param {number} num
   * @return {string}
   * @example getRandom(4) // 0626
   */
  function getRandom(num) {
    var str = '';

    for (var i = 0; i < num; i++) {
      str += Math.floor(Math.random() * 10);
    }

    return str;
  }

  /**
   * @description: 获取滚动条宽度
   * @return {Number}
   */
  function getScrollBarWidth() {
    var el = document.createElement('p');
    var styles = {
      width: '100px',
      height: '100px',
      overflowY: 'scroll'
    };

    for (var _i = 0, _Object$keys = Object.keys(styles); _i < _Object$keys.length; _i++) {
      var k = _Object$keys[_i];
      el.style[k] = styles[k];
    }

    document.body.appendChild(el);
    var scrollBarWidth = el.offsetWidth - el.clientWidth;
    el.parentNode.removeChild(el);
    return scrollBarWidth;
  }

  /**
   * @description: 类型验证获取value，返回默认值
   * @param {*} value
   * @param {Function|Array<Function>} types
   * @param {*} defaultValue
   * @return {*}
   * @example: getTypeValue(1,Number) //1
   * @example: getTypeValue(1,Number,1) //1
   * @example: getTypeValue('0',[String,Number],0) // '0'
   */
  function getTypeValue(value, types, defaultValue) {
    if (!types || !types.length) {
      if (typeof value === 'undefined' && typeof defaultValue !== 'undefined') { return defaultValue; }
      return value;
    }

    types = Array.isArray(types) ? types : [types];
    var valueType = value !== undefined && value !== null ? value.constructor : undefined;
    if (valueType && types.includes(valueType)) { return value; }
    if (typeof defaultValue !== 'undefined') { return defaultValue; }
    return types[0]().valueOf();
  }

  /**
   * @description: 生成一个uid，全局唯一标识符
   * @param {Number} len uid的长度
   * @param {Number} radix 进制数
   * @return {String}
   * @example getUid(12) // 18djrujZHyaO
   */
  function getUid() {
    var len = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 12;
    var radix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
    var uuid = [];
    var i;
    radix = radix > 0 ? radix : chars.length;

    if (len) {
      // Compact form
      for (i = 0; i < len; i++) {
        uuid[i] = chars[0 | Math.random() * radix];
      }
    } else {
      // rfc4122, version 4 form
      var r; // rfc4122 requires these characters

      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
      uuid[14] = '4'; // Fill in random data.  At i==19 set the high bits of clock sequence as
      // per rfc4122, sec. 4.1.5

      for (i = 0; i < 36; i++) {
        if (!uuid[i]) {
          r = 0 | Math.random() * 16;
          uuid[i] = chars[i == 19 ? r & 0x3 | 0x8 : r];
        }
      }
    }

    return uuid.join('');
  }

  /**
   * @description: 获取url参数
   * @param {string} name
   * @param {string?} url 默认 window.location.search
   * @return {string}
   * @example getUrlParam('a','/index?a=1&b=2') // 1
   */
  function getUrlParam(name, url) {
    var reg = new RegExp('(\\?|&|^)' + name + '=([^&]*)(&|$)');
    var r = (url || window.location.search).match(reg);
    return r ? unescape(r[2]) : '';
  }

  /**
   * @description: 是否为promise对象
   * @param {*} value
   * @return {boolean}
   */
  function isPromise(value) {
    return !!value && (_typeof(value) === 'object' || typeof value === 'function') && typeof value.then === 'function';
  }

  /**
   * @description: 加载一张图片
   * @param {String} src
   * @return {Promise}
   */
  function loadImage(src) {
    return new Promise(function (resolve, reject) {
      var img = new Image();
      img.onload = resolve;
      img.onerror = reject;
      img.src = src;
    });
  }

  /**
   * @description: 合并多个class
   * @param {String|object|Array<String|object>} classList
   * @return {String} 返回字符串class
   * @example: mergeClass({a:false},{b:true},'c d ',['e f','g',{h:true}]) //b c d e f g h
   */

  function mergeClass() {
    var arguments$1 = arguments;

    for (var _len = arguments.length, classList = new Array(_len), _key = 0; _key < _len; _key++) {
      classList[_key] = arguments$1[_key];
    }

    return _toConsumableArray(new Set(trim(classList.map(function (item) {
      var type = getType(item);
      var str = '';

      if (type === 'string') {
        str = item;
      } else if (type === 'object') {
        str = Object.keys(item).filter(function (name) {
          return name && item[name];
        }).join(' ');
      } else if (type === 'array') {
        str = mergeClass.apply(void 0, _toConsumableArray(item));
      }

      return str;
    }).join(' ')).split(/\s+/))).join(' ');
  }

  /**
   * @description: 路径拼接
   * @param {String[]} args
   * @return {String}
   * @example mergePath('pages','home') // pages/home
   */
  function mergePath() {
    var arguments$1 = arguments;

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments$1[_key];
    }

    var length = args.length;
    return (length > 1 ? args.map(function (item, index) {
      var path = String(item);

      if (index === 0) {
        return path.replace(/\/+$/g, '');
      } else if (index === length - 1) {
        return path.replace(/^\/+/g, '');
      } else {
        return path.replace(/^\/+|\/+$/g, '');
      }
    }) : args).filter(function (str) {
      return str !== '';
    }).join('/');
  }

  /**
   * @description: 驼峰转-
   * @param {String} str 字符串
   * @param {String} mark 转换符号：-
   * @return {String}
   * @example: toLine('borderRadius')  // border-radius
   */
  function toLine() {
    var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
    var mark = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '-';
    return str.replace(/([A-Z])/g, "".concat(mark, "$1")).toLowerCase();
  }

  /**
   * @description: 合并多个style
   * @param {Array<String|object>} styleList
   * @return {String} 返回字符串style，兼容其它端
   * @example: mergeStyle('width:10rpx',{height:'20rpx',zIndex:2},'border:2rpx') //width:10rpx;height:20rpx;z-index:2;border:2rpx
   */

  function mergeStyle() {
    var arguments$1 = arguments;

    var styleObj = {};

    var addStyle = function addStyle(name, value) {
      name = trim(name);
      value = ['string', 'number'].includes(getType(value)) ? trim(value) : '';
      if (name && value) { styleObj[toLine(name)] = value; }
    };

    for (var _len = arguments.length, styleList = new Array(_len), _key = 0; _key < _len; _key++) {
      styleList[_key] = arguments$1[_key];
    }

    styleList.forEach(function (style) {
      var type = getType(style);

      if (type === 'string') {
        trim(style).replace(/^;+|;+$/, '').split(/;+/).map(function (str) {
          return str.split(/:+/);
        }).forEach(function (_ref) {
          var _ref2 = _slicedToArray(_ref, 2),
              k = _ref2[0],
              value = _ref2[1];

          return addStyle(k, value);
        });
      } else if (type === 'object') {
        Object.keys(style).forEach(function (k) {
          return addStyle(k, style[k]);
        });
      }
    });
    return Object.keys(styleObj).map(function (k) {
      return "".concat(k, ":").concat(styleObj[k]);
    }).join(';');
  }

  /**
   * @description: 设备信息
   */
  var inBrowser = typeof window !== 'undefined';
  var ua = inBrowser ? window.navigator.userAgent.toLowerCase() : '';
  var isMobile = !!ua.match(/AppleWebKit.*Mobile.*/i);
  var isWeixin = !!ua.match(/MicroMessenger/i);
  var isIE = /msie|trident/.test(ua);
  var isIE9 = ua.indexOf('msie 9.0') > 0;
  var isEdge = ua.indexOf('edge/') > 0;
  var isAndroid = ua.indexOf('android') > 0;
  var isIOS = /iphone|ipad|ipod|ios/.test(ua);
  var isChrome = /chrome\/\d+/.test(ua) && !isEdge;
  var isIPhone = ua.indexOf('iphone') > -1; // 是否为iPhone或者QQHD浏览器

  var isIPad = ua.indexOf('ipad') > -1; // 是否iPad

  var isWebApp = ua.indexOf('safari') === -1; // 是否web应该程序，没有头部与底部

  var hasTouch = isMobile;
  var mousedown = hasTouch ? 'touchstart' : 'mousedown';
  var mousemove = hasTouch ? 'touchmove' : 'mousemove';
  var mouseup = hasTouch ? 'touchend' : 'mouseup';
  var windowWidth = window.innerWidth;
  var windowHeight = window.innerHeight;
  var systemInfo = {
    inBrowser: inBrowser,
    ua: ua,
    isMobile: isMobile,
    isWeixin: isWeixin,
    isIE: isIE,
    isIE9: isIE9,
    isEdge: isEdge,
    isAndroid: isAndroid,
    isIOS: isIOS,
    isChrome: isChrome,
    isIPhone: isIPhone,
    isIPad: isIPad,
    isWebApp: isWebApp,
    hasTouch: hasTouch,
    mousedown: mousedown,
    mousemove: mousemove,
    mouseup: mouseup,
    windowWidth: windowWidth,
    windowHeight: windowHeight
  };

  /**
   * @description: 动画执行时机
   * @param {Function} fn
   * @return {void}
   */

  function nextFrame(fn) {
    var raf = systemInfo.inBrowser && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : setTimeout;
    return raf(function () {
      return raf(fn, 5);
    }, 5);
  }

  /**
   * @description: 隐藏手机号码中的几位数字加密显示
   * @param {String} phone
   * @return {String}
   * @example privatePhone('15234856547') // 152****6547
   */
  function privatePhone(phone) {
    return ('' + phone).replace(/^(\d{3})\d{4}(\d{4})$/g, '$1****$2');
  }

  /**
   * @description: 移除class
   * @param {string|Element|Element[]} selector
   * @param {string} value
   * @return {void}
   * @example removeClass('body', 'class1')
   */

  function removeClass(selector, value) {
    value = trim(value);

    if (value) {
      var classes = value.split(/\s+/g);
      getElem(selector).forEach(function (el) {
        var cur = (el.getAttribute('class') || '').trim();

        if (cur && (cur = ' ' + cur + ' ')) {
          classes.forEach(function (cls) {
            if (cur.indexOf(' ' + cls + ' ') > -1) {
              cur = cur.replace(' ' + cls + ' ', ' ');
            }
          });

          if (cur && (cur = cur.trim())) {
            el.setAttribute('class', cur);
          } else {
            el.removeAttribute('class');
          }
        }
      });
    }
  }

  /**
   * @description: 适配屏幕
   * @param {Number} size 尺寸
   * @param {Number} styleWidth 设计稿尺寸，默认375
   * @return {Number}
   */

  function shfitSize(size) {
    var styleWidth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 375;
    return parseInt(size / (styleWidth / systemInfo.windowWidth));
  }

  /**
   * @description: 函数节流
   * @param {Function} func 回调函数
   * @param {Number} wait 等待时间
   * @param {{leading:Boolean,trailing:Boolean}} options
   * @return {Function}
   * @example const func = throttle(()=>console.log(1),100);
   */
  function throttle(func) {
    var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
    var options = arguments.length > 2 ? arguments[2] : undefined;
    var timeout, context, args, result; // 上一次执行回调的时间戳

    var previous = 0; // 无传入参数时，初始化 options 为空对象

    if (!options) { options = {}; }

    var later = function later() {
      // 当设置 { leading: false } 时
      // 每次触发回调函数后设置 previous 为 0
      // 不然为当前时间
      previous = options.leading === false ? 0 : Date.now(); // 防止内存泄漏，置为 null 便于后面根据 !timeout 设置新的 timeout

      timeout = null; // 执行函数

      result = func.apply(context, args);
      if (!timeout) { context = args = null; }
    }; // 每次触发事件回调都执行这个函数
    // 函数内判断是否执行 func
    // func 才是我们业务层代码想要执行的函数


    function throttled() {
      // 记录当前时间
      var now = Date.now(); // 第一次执行时（此时 previous 为 0，之后为上一次时间戳）
      // 并且设置了 { leading: false }（表示第一次回调不执行）
      // 此时设置 previous 为当前值，表示刚执行过，本次就不执行了

      if (!previous && options.leading === false) { previous = now; } // 距离下次触发 func 还需要等待的时间

      var remaining = wait - (now - previous);
      context = this;
      args = arguments; // 要么是到了间隔时间了，随即触发方法（remaining <= 0）
      // 要么是没有传入 {leading: false}，且第一次触发回调，即立即触发
      // 此时 previous 为 0，wait - (now - previous) 也满足 <= 0
      // 之后便会把 previous 值迅速置为 now

      if (remaining <= 0 || remaining > wait) {
        if (timeout) {
          clearTimeout(timeout); // clearTimeout(timeout) 并不会把 timeout 设为 null
          // 手动设置，便于后续判断

          timeout = null;
        } // 设置 previous 为当前时间


        previous = now; // 执行 func 函数

        result = func.apply(context, args);
        if (!timeout) { context = args = null; }
      } else if (!timeout && options.trailing !== false) {
        // 最后一次需要触发的情况
        // 如果已经存在一个定时器，则不会进入该 if 分支
        // 如果 {trailing: false}，即最后一次不需要触发了，也不会进入这个分支
        // 间隔 remaining milliseconds 后触发 later 方法
        timeout = setTimeout(later, remaining);
      }

      return result;
    } // 手动取消


    throttled.cancel = function () {
      clearTimeout(timeout);
      previous = 0;
      timeout = context = args = null;
    };

    return throttled;
  }

  /**
   * @description: 数字保留几位小数
   * @param {Number|String} number 数字
   * @param {Number} digits 小数位数
   * @return {String}
   * @example: toFixed(1234.25555,2) // '1234.25'
   */
  function toFixed(number) {
    var digits = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
    var str = '' + number;
    var decimalIndex = str.lastIndexOf('.');
    var decimal = (decimalIndex > -1 ? str.substr(decimalIndex + 1, digits) : '').padEnd(digits, '0');
    return '' + parseInt(number) + (decimal.length ? '.' + decimal : '');
  }

  /**
   * @description: -转驼峰
   * @param {String} str 字符串
   * @param {String} mark 转换符号：-
   * @return {String}
   * @example: toHump('border-radius')  // borderRadius
   */
  function toHump() {
    var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
    var mark = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '-';
    return str.replace(new RegExp("".concat(mark, "(\\w)"), 'g'), function (all, letter) {
      return letter.toUpperCase();
    });
  }

  /**
   * @description: 把不规则的数据格式转换为统一的数组[{value:'1'，label:'文字'}]数据格式
   * @param {Array|object} data
   * @param {string} valueKey
   * @param {string} labelKey
   * @return {Array}
   */

  function toValidListData(data) {
    var valueKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'value';
    var labelKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'label';
    var list = [];
    var type = getType(data);

    if (type === 'object') {
      each(data, function (item, k) {
        var obj = {};

        if (trim(valueKey)) {
          obj[valueKey] = k;
        }

        if (trim(labelKey)) {
          obj[labelKey] = item;
        }

        list.push(obj);
      });
    } else if (type === 'array') {
      each(data, function (item) {
        if (getType(item) === 'object') {
          list.push(item);
        } else {
          var obj = {};

          if (trim(valueKey)) {
            obj[valueKey] = item;
          }

          if (trim(labelKey)) {
            obj[labelKey] = item;
          }

          list.push(obj);
        }
      });
    }

    return list;
  }

  var resize;
  /**
   * @description: 使用rem
   * @param {Number} styleWidth 设计稿px，默认375
   * @param {Number} remUnit 比例默认100
   * @return {void}
   */

  function useRem() {
    var styleWidth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 375;
    var remUnit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;

    if (!resize && document && document.addEventListener) {
      var html = document.documentElement;

      resize = function resize() {
        html.style.fontSize = remUnit * (html.clientWidth / styleWidth) + 'px';
      };

      window.addEventListener('orientationchange' in window ? 'orientationchange' : 'resize', resize);
      document.addEventListener('DOMContentLoaded', resize);
      resize();
    }
  }

  /**
   * @description: utf16to8
   * @param {String} str
   * @return {String}
   */
  function utf16to8(str) {
    var out, i, len, c;
    out = '';
    len = str.length;

    for (i = 0; i < len; i++) {
      c = str.charCodeAt(i);

      if (c >= 0x0001 && c <= 0x007f) {
        out += str.charAt(i);
      } else if (c > 0x07ff) {
        out += String.fromCharCode(0xe0 | c >> 12 & 0x0f);
        out += String.fromCharCode(0x80 | c >> 6 & 0x3f);
        out += String.fromCharCode(0x80 | c >> 0 & 0x3f);
      } else {
        out += String.fromCharCode(0xc0 | c >> 6 & 0x1f);
        out += String.fromCharCode(0x80 | c >> 0 & 0x3f);
      }
    }

    return out;
  }

  /**
   * @description: utf8to16
   * @param {String} str
   * @return {String}
   */
  function utf8to16(str) {
    var out, i, len, c;
    var char2, char3;
    out = '';
    len = str.length;
    i = 0;

    while (i < len) {
      c = str.charCodeAt(i++);

      switch (c >> 4) {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
          out += str.charAt(i - 1);
          break;

        case 12:
        case 13:
          char2 = str.charCodeAt(i++);
          out += String.fromCharCode((c & 0x1f) << 6 | char2 & 0x3f);
          break;

        case 14:
          char2 = str.charCodeAt(i++);
          char3 = str.charCodeAt(i++);
          out += String.fromCharCode((c & 0x0f) << 12 | (char2 & 0x3f) << 6 | (char3 & 0x3f) << 0);
          break;
      }
    }

    return out;
  }

  /*
   * @description: regExp
   * @Descripttion: 常用验证方法
   * @Author: 无痕
   * @Date: 2019-09-23 15:53:33
   * @LastEditors: 无痕
   * @LastEditTime: 2021-09-29 14:28:51
   */

  /**
   * @description: 是否为整数
   * @param {string|number} val
   * @return {boolean}
   */
  function isInteger(val) {
    return /^[1-9]\d*$/.test(val);
  }
  /**
   * @description: 是否为正确的手机号码格式
   * @param {string} val
   * @return {boolean}
   */


  function isPhone(val) {
    return /^1[3456789]\d{9}$/g.test(val);
  }
  /**
   * @description: 是否为电子邮箱地址
   * @param {string} val
   * @return {boolean}
   */


  function isEmail(val) {
    return /^([a-zA-Z0-9]+[_|_|\-|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|_|.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,6}$/.test(val);
  }
  /**
   * @description: 是否带有域名
   * @param {string} val
   * @return {boolean}
   */


  function hasHost(val) {
    return /^(https|http|\/{2}|ftp|rtsp|mms)/.test(val);
  }
  /**
   * @description: 是否带有表情字符
   * @param {string} val
   * @return {boolean}
   */


  function hasEmoj(val) {
    return /[^\u0020-\u007E\u00A0-\u00BE\u2E80-\uA4CF\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFFEF\u0080-\u009F\u2000-\u201f\u2026\u2022\u20ac\r\n]/g.test(val);
  }
  /**
   * @description: 是否为有效的身份证号码
   * @param {string} idCard
   * @return {boolean}
   */


  function isIdCard(idCard) {
    // 15位和18位身份证号码的正则表达式
    var regIdCard = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/; // 如果通过该验证，说明身份证格式正确，但准确性还需计算

    if ((idCard = String(idCard)) && regIdCard.test(idCard)) {
      if (idCard.length === 18) {
        // 将前17位加权因子保存在数组里
        var idCardWi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; // 这是除以11后，可能产生的11位余数、验证码，也保存成数组

        var idCardY = [1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2]; // 用来保存前17位各自乖以加权因子后的总和

        var idCardWiSum = 0;

        for (var i = 0; i < 17; i++) {
          idCardWiSum += idCard.substring(i, i + 1) * idCardWi[i];
        }

        var idCardMod = idCardWiSum % 11; // 计算出校验码所在数组的位置

        var idCardLast = idCard.substring(17); // 得到最后一位身份证号码
        // 如果等于2，则说明校验码是10，身份证号码最后一位应该是X

        if (idCardMod === 2) {
          if (idCardLast == 'X' || idCardLast == 'x') {
            return true;
          }
        } else {
          // 用计算出的验证码与最后一位身份证号码匹配，如果一致，说明通过，否则是无效的身份证号码
          if (idCardLast == idCardY[idCardMod]) {
            return true;
          }
        }
      }
    }

    return false;
  }
  /**
   * @description: 中文姓名判断
   * @param {string} name
   * @param {number} length
   * @return {boolean}
   */


  function isNameZh(name) {
    var length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
    return new RegExp("/^[\u4E00-\u9FA5]{".concat(length, ",}$/")).test(name);
  }
  /**
   * @description: 港澳居民来往内地通行证，规则： H/M + 10位或6位数字，样本： H1234567890
   * @param {string} card
   * @return {boolean}
   */


  function isHKCard(card) {
    return /^([A-Z]\d{6,10}(\(\w{1}\))?)$/.test(card);
  }
  /**
   * @description: 台湾居民来往大陆通行证，规则： 新版8位或18位数字， 旧版 英文字母 + 10位数字，样本： 12345678 或 1234567890B
   * @param {string} card
   * @return {boolean}
   */


  function isTWCard(card) {
    return /^(\d{8}|[a-zA-Z0-9]{10}|\d{18})$/.test(card);
  }
  /**
   * @description: 中国护照
   * @param {string} val
   * @return {boolean}
   */


  function isPassport(val) {
    return /(^[CcTtEeKkGgDdSsPpHh]\d{8}$)|(^(([Ee][a-fA-F])|([DdSsPp][Ee])|([Kk][Jj])|([Mm][Aa])|(1[45]))\d{7}$)/.test(val);
  }
  /**
   * @description: 军官证，规则： 军/兵/士/文/职/广/（其他中文） + "字第" + 4到8位字母或数字 + "号"，样本： 军字第2001988号, 士字第P011816X号
   * @param {string} card
   * @return {boolean}
   */


  function isOfficerCard(card) {
    return /^[\u4E00-\u9FA5](字第)([0-9a-zA-Z]{4,8})(号?)$/.test(card);
  }

  var validate = {
    isInteger: isInteger,
    isPhone: isPhone,
    isEmail: isEmail,
    hasHost: hasHost,
    hasEmoj: hasEmoj,
    isIdCard: isIdCard,
    isNameZh: isNameZh,
    isHKCard: isHKCard,
    isTWCard: isTWCard,
    isPassport: isPassport,
    isOfficerCard: isOfficerCard
  };

  var version = '4.0.0';

  exports.EventEmit = EventEmit;
  exports.addClass = addClass;
  exports.addUnit = addUnit;
  exports.arrayDifference = arrayDifference;
  exports.arrayFind = arrayFind;
  exports.arrayIntersect = arrayIntersect;
  exports.arrayUnion = arrayUnion;
  exports.base64 = base64;
  exports.bridge = bridge;
  exports.callPhone = callPhone;
  exports.cookieStorage = cookieStorage;
  exports.copyText = copyText;
  exports.countDown = countDown;
  exports.createTimer = createTimer;
  exports.debounce = debounce;
  exports.downloadBlob = downloadBlob;
  exports.each = each;
  exports.extend = extend;
  exports.formatDate = formatDate;
  exports.formatDateRange = formatDateRange;
  exports.formatDay = formatDay;
  exports.formatDiffTime = formatDiffTime;
  exports.formatMoney = formatMoney;
  exports.formatNumber = formatNumber;
  exports.getAstro = getAstro;
  exports.getDaysInMonth = getDaysInMonth;
  exports.getElem = getElem;
  exports.getMatcheds = getMatcheds;
  exports.getMaxZindex = getMaxZindex;
  exports.getRandom = getRandom;
  exports.getScrollBarWidth = getScrollBarWidth;
  exports.getType = getType;
  exports.getTypeValue = getTypeValue;
  exports.getUid = getUid;
  exports.getUrlParam = getUrlParam;
  exports.hasOwnProp = hasOwnProp;
  exports.isArray = isArray;
  exports.isArrayLike = isArrayLike;
  exports.isDef = isDef;
  exports.isFunction = isFunction;
  exports.isNumber = isNumber;
  exports.isObject = isObject;
  exports.isPlainObject = isPlainObject;
  exports.isPromise = isPromise;
  exports.isValidDate = isValidDate;
  exports.loadImage = loadImage;
  exports.mergeClass = mergeClass;
  exports.mergePath = mergePath;
  exports.mergeStyle = mergeStyle;
  exports.nextFrame = nextFrame;
  exports.noop = noop;
  exports.parseDate = parseDate;
  exports.parseMilliseconds = parseMilliseconds;
  exports.parseSeconds = parseSeconds;
  exports.privatePhone = privatePhone;
  exports.removeClass = removeClass;
  exports.shfitSize = shfitSize;
  exports.systemInfo = systemInfo;
  exports.throttle = throttle;
  exports.toArray = toArray;
  exports.toFixed = toFixed;
  exports.toHump = toHump;
  exports.toLine = toLine;
  exports.toValidListData = toValidListData;
  exports.trim = trim;
  exports.useRem = useRem;
  exports.utf16to8 = utf16to8;
  exports.utf8to16 = utf8to16;
  exports.validate = validate;
  exports.version = version;

  Object.defineProperty(exports, '__esModule', { value: true });

})));
